


package spotor.client.service;

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.client.HttpClient;
import org.apache.http.entity.HttpEntityWrapper;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HttpContext;
import org.xmlpull.v1.XmlPullParserException;

import spotor.client.R;
import spotor.client.io.LocalExecutor;
import spotor.client.io.LocalPlanHandler;
import spotor.client.io.RemoteExecutor;
import spotor.client.io.RemotePlanHandler;
import spotor.client.io.XmlHandler.HandlerException;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.text.format.DateUtils;
import android.text.style.BulletSpan;
import android.util.Log;
import android.content.Context;

public class SyncService extends IntentService {
	
	private final static String TAG = "SyncService";
	public static final String EXTRA_STATUS_RECEIVER =
        "com.spotor.android.extra.STATUS_RECEIVER";
	public static final int STATUS_RUNNING = 0x1;
    public static final int STATUS_ERROR = 0x2;
    public static final int STATUS_FINISHED = 0x3;
    
	private static final int SECOND_IN_MILLIS = (int) DateUtils.SECOND_IN_MILLIS;
	private static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
	private static final String ENCODING_GZIP = "gzip";
	//Service Url
	private final String SERVICE_URL = "http://www.spotor.com/";
	
	private static final int VERSION_NONE = 0;
    private static final int VERSION_CURRENT = 5;
	
	private LocalExecutor mLocalExecutor;
	private RemoteExecutor mRemoteExecutor;
	
	public SyncService()
	{
		super(TAG);
	}
	
	public SyncService(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		// TODO Auto-generated method stub
		final ResultReceiver receiver = intent.getParcelableExtra(EXTRA_STATUS_RECEIVER);
        if (receiver != null) receiver.send(STATUS_RUNNING, Bundle.EMPTY);
		
		final Context context = this;
		final SharedPreferences prefs = getSharedPreferences(Prefs.SPOTOR_SYNC,
	                Context.MODE_PRIVATE);
		final int localVersion = prefs.getInt(Prefs.LOCAL_VERSION, VERSION_NONE);
		
		try {
			final long startLocal = System.currentTimeMillis();
            final boolean localParse = localVersion < VERSION_CURRENT;
			if(localParse)
			{
				// Load static local data
				mLocalExecutor.execute(R.xml.plans, new LocalPlanHandler());
				
				// Parse values from local cache first, since spreadsheet copy
                // or network might be down.
				mLocalExecutor.execute(context,"cache-plans.xml",new RemotePlanHandler());
				
				// Save local parsed version
				prefs.edit().putInt(Prefs.LOCAL_VERSION, VERSION_CURRENT).commit();
			}
			//保持远程更新
			final long startRemote = System.currentTimeMillis();
			mRemoteExecutor
			.executeGet(SERVICE_URL,new RemotePlanHandler());
			Log.d(TAG, "同步本地文件用了"+(System.currentTimeMillis() - startLocal)+"微秒");
		} catch (Exception e){
			Log.e(TAG,"同步出现问题",e);
			
			if(receiver != null){
				final Bundle bundle = new Bundle();
				bundle.putString(Intent.EXTRA_TEXT,e.toString());
				receiver.send(STATUS_ERROR, bundle);
			}
		}
		//同步成功
		Log.d(TAG, "同步完成！");
		if (receiver != null)receiver.send(STATUS_FINISHED, Bundle.EMPTY);
	}
	
	/**
     * Generate and return a {@link HttpClient} configured for general use,
     * including setting an application-specific user-agent string.
     */
    public static HttpClient getHttpClient(Context context) {
        final HttpParams params = new BasicHttpParams();

        // Use generous timeouts for slow mobile networks
        HttpConnectionParams.setConnectionTimeout(params, 20 * SECOND_IN_MILLIS);
        HttpConnectionParams.setSoTimeout(params, 20 * SECOND_IN_MILLIS);

        HttpConnectionParams.setSocketBufferSize(params, 8192);
        HttpProtocolParams.setUserAgent(params, buildUserAgent(context));

        final DefaultHttpClient client = new DefaultHttpClient(params);
        
        client.addRequestInterceptor(new HttpRequestInterceptor() {
            public void process(HttpRequest request, HttpContext context) {
                // Add header to accept gzip content
                if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {
                    request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
                }
            }
        });
        
        client.addResponseInterceptor(new HttpResponseInterceptor() {
            public void process(HttpResponse response, HttpContext context) {
                // Inflate any responses compressed with gzip
                final HttpEntity entity = response.getEntity();
                final Header encoding = entity.getContentEncoding();
                if (encoding != null) {
                    for (HeaderElement element : encoding.getElements()) {
                        if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {
                            response.setEntity(new InflatingEntity(response.getEntity()));
                            break;
                        }
                    }
                }
            }
        });
        
        return client;
    }

	private static String buildUserAgent(Context context) {
		// TODO Auto-generated method stub
		return null;
	}
	 /**
     * Simple {@link HttpEntityWrapper} that inflates the wrapped
     * {@link HttpEntity} by passing it through {@link GZIPInputStream}.
     */
    private static class InflatingEntity extends HttpEntityWrapper {
        public InflatingEntity(HttpEntity wrapped) {
            super(wrapped);
        }

        @Override
        public InputStream getContent() throws IOException {
            return new GZIPInputStream(wrappedEntity.getContent());
        }

        @Override
        public long getContentLength() {
            return -1;
        }
    }

	
	private interface Prefs {
        String SPOTOR_SYNC = "spotor_sync";
        String LOCAL_VERSION = "local_version";
    }
}
